import os,tempfile,uuid,shutil,commands

import time
import logging
log = logging.getLogger(__name__)

from crv.model.crvmodel import *
from crv.model.rp import *

from crv.tools.certstoremgr import CertStoreMgr

from sqlalchemy.orm import mapper

import pickle
import socket
import fcntl
import struct

import base64

class CentOS5_Puppet_ClientMaker(ClientMaker):

    def get_ip_address(self, ifname):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        return socket.inet_ntoa(fcntl.ioctl(
            s.fileno(),
            0x8915,  # SIOCGIFADDR
            struct.pack('256s', ifname[:15])
            )[20:24])
    
            
    def __new__(cls, *args, **kwds):
        cls.__clients={}
        return AttrContainer.__new__(cls, *args, **kwds)

    def __init__(self,name, doc="",templatedir="/opt/cloudcrv/cloudcrv/crvclient"):

        super(CentOS5_Puppet_ClientMaker, self).__init__("centos5_puppet")

        #Map of "clientuuid->pathToTarredBase64file
        self.__clients={}
        self.setAttr("name",name)
        self.setAttr("doc",doc)        
        self.setAttr("templatedir",templatedir)

    def __del__(self):
        for icl in self.__clients.keys():
            self.expireClient(icl)
            
    def makeClient(self,vm):
        """will return a dict {clientuuid->path to a userdata file}"""
        myuuid=str(uuid.uuid4())
        workdir=tempfile.gettempdir()+"/"+myuuid
        clientdir=workdir+"/crvclient"
        tarfile=workdir+"/client.tgz"
        base64file=workdir+".tgz.base64"
        
        #FIXME: assuming uuid never duplicates
        os.makedirs(workdir,0700)

        shutil.copytree(self.getAttr("templatedir"),clientdir)

        #create the python info for this vm
        ouf=open(clientdir+"/"+"values.pickle","w")
        pickle.dump(vm.VM_ID,ouf)
#        pickle.dump("https://%s:8080/status/"%self.get_ip_address('eth0'),ouf)
        pickle.dump("https://cloudcrvsrv:8080/status/",ouf)
        pickle.dump(self.get_ip_address('eth0'),ouf)

        certname = vm.generateCertName()
        
        log.debug("Certname=%s"%certname)
        pickle.dump(certname, ouf)

        ouf.close()

        #Generate a cert
        caMgr=CertStoreMgr.getInstance()

        log.debug("capubkey=%s"%caMgr.getCAPublicKeyPEM())
        log.debug("myuuid=%s"%myuuid)
        log.debug("workdir=%s"%workdir)
        log.debug("clientdir=%s"%clientdir)
        log.debug("tarfile=%s"%tarfile)
        log.debug("base64file=%s"%base64file)
        log.debug("pid=%s"%os.getpid())

        caMgr.generateCert(certname)
#        print caMgr.getCertPEM(certname)

        ouf=open("%s/%s.pass"%(clientdir,certname),"w")
        ouf.write(caMgr.getPassword(certname))
        ouf.close()
        
        ouf=open("%s/ca.crt"%clientdir,"w")
        ouf.write(caMgr.getCACertPEM())
        ouf.close()

        ouf=open("%s/%s.crt"%(clientdir,certname),"w")
        ouf.write(caMgr.getCertPEM(certname))
        ouf.close()

        ouf=open("%s/%s.prk"%(clientdir,certname),"w")
        ouf.write(caMgr.getPrivateKeyPEM(certname))
        ouf.close()

        ouf=open("%s/%s.puk"%(clientdir,certname),"w")
        ouf.write(caMgr.getPublicKeyPEM(certname))
        ouf.close()
        
        #tar and base64 the dir to a file
        cmdstr="tar czf %s -C %s %s --exclude=\".svn\""%(tarfile,workdir,"crvclient")
        (status,output)=commands.getstatusoutput(cmdstr)
        if status!=0:
            raise RuntimeError("CentOS5_Puppet_ClientMaker::makeClient:: can't execute %s,output=%s, status=%d"%(cmdstr,output,status))

        """
        #read in the tar file
        inf=open(tarfile,"rb")
        tarfilebuf=inf.read()
        inf.close()
        b64tarfilebuf=base64.urlsafe_b64encode(tarfilebuf)
        """        

        cmdstr="base64 -w 0 %s"%tarfile
        (status,b64tarfilebuf)=commands.getstatusoutput(cmdstr)
        if status!=0:
            raise RuntimeError("CentOS5_Puppet_ClientMaker::makeClient:: can't execute %s,output=%s, status=%d"%(cmdstr,output,status))
        ouf=open(base64file,"w")
        ouf.write(b64tarfilebuf)
        ouf.close()

        #put it to my collection and hand it back
        self.__clients[myuuid]=base64file

        #remove workdir
        shutil.rmtree(workdir,ignore_errors=True)

        return (myuuid,base64file)
        
    def expireClient(self,icl):
        return
        os.remove(self.__clients[icl])
        self.__clients.pop(icl)

